﻿
Imports std

Public Class _rcserve(Of ASYNC_T, SERVER_T As {tcpServer3, New}, TALKHANDLER_T As tcpServer3.talkHandler)
    Protected WithEvents server As SERVER_T = Nothing
    Private invokers As map(Of String, pair(Of Type(), _do(Of fromBytes(), pointer(Of toBytes()), ASYNC_T))) = Nothing

    Public Sub New()
        server = New SERVER_T()
        invokers = New map(Of String, pair(Of Type(), _do(Of fromBytes(), pointer(Of toBytes()), ASYNC_T)))()
    End Sub

    Public Property connectionCount As Int64
        Get
            Return server.maxConnectionCount
        End Get
        Set(value As Int64)
            server.maxConnectionCount = value
        End Set
    End Property

    Public Function register(ByVal name As String,
                             ByVal invoke As _do(Of fromBytes(), pointer(Of toBytes()), ASYNC_T),
                             ByVal ParamArray argTypes() As Type) As Boolean
        If isemptystring(name) Then
            raiseError("cannot register function with no name.", errorHandle.errorType.warning)
            Return False
        End If
        If invoke Is Nothing Then
            raiseError("invoke function is nothing.", errorHandle.errorType.warning)
            Return False
        End If
        If invokers.find(name) <> invokers.end() Then
            raiseError("caught an existing function named " + name + ", cannot register with same name.", _
                       errorHandle.errorType.warning)
            Return False
        End If

        If isdebugmode() Then
            raiseError("register remotecall invoke, name " + name + ", invoke method " + invokeMethodName(invoke))
        End If

        Return invokers.insert(name, make_pair(argTypes, invoke)) <> invokers.end()
    End Function

    Public Function [erase](ByVal name As String) As Boolean
        Return invokers.erase(name)
    End Function

    Public Sub clear()
        invokers.clear()
    End Sub

    Public Function start() As Boolean
        Return server.start()
    End Function

    Public Function start(ByVal port As Int32) As Boolean
        Return server.start(port)
    End Function

    Public Sub [stop]()
        server.stop()
    End Sub

    Public Sub [stop](ByVal waittime As Int64)
        server.stop(waittime)
    End Sub

    Protected Function invoke(ByVal handler As TALKHANDLER_T,
                              ByRef rtns As pointer(Of toBytes()),
                              ByRef async As ASYNC_T,
                              ByRef types() As Type) As Boolean
        Dim name As String = Nothing
        If protocol.getname(handler.receiveData(), name) Then
            If envs.nettrace() AndAlso isdebugmode() Then
                raiseError(errorHandle.errorType.application,
                           "receive rcserve call ", name, " from ", handler)
            End If
            Dim it As map(Of String, 
                          pair(Of Type(), _do(Of fromBytes(), pointer(Of toBytes()), ASYNC_T))).iterator = Nothing
            it = invokers.find(name)
            If it = invokers.end() Then
                raiseError(errorHandle.errorType.user, "no function ", name, " registered, ignore.")
            Else
                Dim invoker As _do(Of fromBytes(), pointer(Of toBytes()), ASYNC_T) = Nothing
                types = (+it).second.first
                invoker = (+it).second.second
                Dim args() As fromBytes = Nothing
                If protocol.read(handler.receiveData(), args, types, 1) Then
                    rtns = New pointer(Of toBytes())()
                    async = do_(invoker, args, rtns, Nothing)
                    Return True
                Else
                    raiseError(errorHandle.errorType.user,
                               "cannot get parameters from request ", Convert.ToString(handler), ", ignore.")
                End If
            End If
        Else
            raiseError(errorHandle.errorType.user,
                       "no function name got from request ", Convert.ToString(handler), ", ignore.")
        End If

        Return False
    End Function
End Class
